#ifndef esda_VectorOperatorStream_h
#define esda_VectorOperatorStream_h

/*
 * Copyright (C) Olivier Le Floch
 *
 * See the file LICENSE for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "common.h"
#include "Timestamp.h"
#include "Streams.h"
#include <vector>

namespace esda
{
	template<typename Value>
	class VectorOperatorStream : public OperatorStream<Value> {
	protected:
		vector<Stream<Value>&>& streamVector;
		
	public:
		VectorOperatorStream(vector<Stream<Value>&>& strVect) : streamVector(strVect) {};
		
		virtual Timestamp getNextStart(const Timestamp t) const;
		virtual Timestamp getNextEnd(const Timestamp t) const;
		virtual Timestamp getPreviousStart(const Timestamp t) const;
		virtual Timestamp getPreviousEnd(const Timestamp t) const;
		
		virtual Timestamp getFirstStart() const;
		virtual Timestamp getLastEnd() const;
		
		virtual Value get(const Timestamp t) const;
	};
	
	template<typename Value>
	class VectorOperatorStream_UserFunc : public VectorOperatorStream<Value> {
	public:
		typedef Value (*UserFunc)(vector<Value>);
		
		VectorOperatorStream_UserFunc(vector<Stream<Value>&>& strVect, UserFunc userF) : VectorOperatorStream<Value>(strVect), userFunc(userF) {};
		
		virtual double get(const Timestamp t) const;
	
	private:
		UserFunc userFunc;
	};
	
	template<>
	double VectorOperatorStream<double>::get(const Timestamp t) const {
		return streamVector[0].get(t);
	}
	
	Timestamp VectorOperatorStream::getNextStart(const Timestamp t) const {
		return streamVector[0].getNextStart(t);
	}
	
	Timestamp VectorOperatorStream::getNextEnd(const Timestamp t) const {
		return streamVector[0].getNextEnd(t);
	}
	
	Timestamp VectorOperatorStream::getPreviousStart(const Timestamp t) const {
		return streamVector[0].getPreviousStart(t);
	}

	Timestamp VectorOperatorStream::getPreviousEnd(const Timestamp t) const {
		return streamVector[0].getPreviousEnd(t);
	}

	Timestamp VectorOperatorStream::getFirstStart() const {
		return streamVector[0].getFirstStart();
	}
	
	Timestamp VectorOperatorStream::getLastEnd() const {
		return streamVector[0].getLastEnd();
	}
	
	Value VectorOperatorStream_UserFunc::get(const Timestamp t) const {
		vector values();
		size_t taille = streamVector.size();
		
		for (size_t i = 0; i < taille; i++) {
			values.push_back(streamVector[i].get(t))
		}
		
		return userFunc(values);
	}
}

#endif
